package com.neusoft.neuiotms.dcom.task.hn;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.neusoft.bizcore.notice.constant.NoticeConsts;
import com.neusoft.bizcore.notice.notification.dto.NoticeDingDTO;
import com.neusoft.bizcore.notice.notification.dto.NoticeRecordDTO;
import com.neusoft.bizcore.notice.notification.dto.NoticeRecordSystemDTO;
import com.neusoft.bizcore.schedule.service.JobMgrService;
import com.neusoft.bizcore.web.dto.result.ResultListDTO;
import com.neusoft.bizcore.web.utils.JsonUtils;
import com.neusoft.bizcore.web.utils.id.BaseIdGenerator;
import com.neusoft.neuiotms.dcom.constants.DCOMConstants;
import com.neusoft.neuiotms.dcom.converter.hn.HnInspectionTaskAssetConverter;
import com.neusoft.neuiotms.dcom.model.Holiday;
import com.neusoft.neuiotms.dcom.model.Institutions;
import com.neusoft.neuiotms.dcom.model.ResidentUser;
import com.neusoft.neuiotms.dcom.model.enums.HnInspectionTaskItemStatus;
import com.neusoft.neuiotms.dcom.model.enums.HnInspectionTaskStatus;
import com.neusoft.neuiotms.dcom.model.hn.HnInspectionItem;
import com.neusoft.neuiotms.dcom.model.hn.HnInspectionPlan;
import com.neusoft.neuiotms.dcom.model.hn.HnInspectionTask;
import com.neusoft.neuiotms.dcom.model.hn.HnInspectionTaskAsset;
import com.neusoft.neuiotms.dcom.model.hn.HnInspectionTaskItemValue;
import com.neusoft.neuiotms.dcom.repository.HolidayRepository;
import com.neusoft.neuiotms.dcom.repository.InstitutionsRepository;
import com.neusoft.neuiotms.dcom.repository.hn.HnInspectionItemRepository;
import com.neusoft.neuiotms.dcom.repository.hn.HnInspectionPlanRepository;
import com.neusoft.neuiotms.dcom.repository.hn.HnInspectionTaskRepository;
import com.neusoft.neuiotms.micro.dcam.DcamMicroService;
import com.neusoft.neuiotms.micro.notice.NoticeMicroService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class HnInspectionTaskGenService {
    private final static String LOG_PREFIX = "海南每日巡检";

    @Autowired
    private HnInspectionPlanRepository planRepository;

    @Autowired
    private HnInspectionTaskRepository taskRepository;

    @Autowired
    private JobMgrService jobMgrService;

    @Autowired
    private HolidayRepository holidayRepository;

    @Autowired
    private DcamMicroService dcamMicroService;

    @Autowired
    private HnInspectionTaskAssetConverter hnInspectionTaskAssetConverter;

    @Autowired
    private BaseIdGenerator hnInspectionTaskCodeGenerator;

    @Autowired
    private InstitutionsRepository institutionsRepository;

    @Autowired
    private HnInspectionItemRepository hnInspectionItemRepository;

    @Autowired
    private NoticeMicroService noticeMicroService;

    public void executeInternal(final long inspecitonRuleId) {
        HnInspectionTaskGenService.log.info("{},定时生成每日巡检任务", HnInspectionTaskGenService.LOG_PREFIX);
        //任务开始执行时间
        final Date now = DateUtils.truncate(new Date(), Calendar.HOUR);
        final String nowStr = DateFormatUtils.format(now, "yyyy-MM-dd HH:mm");
        HnInspectionTaskGenService.log.info("{},当前时间: {}", HnInspectionTaskGenService.LOG_PREFIX, nowStr);

        //        final LocalDateTime startTaskTime = LocalDateTime.now().withSecond(0).withNano(0);
        //        HnInspectionTaskGenService.log.info("startTaskTime: " + startTaskTime);
        final Calendar calendar = Calendar.getInstance();
        final List<Holiday> lists =
                this.holidayRepository.findByDate(DateUtils.round(calendar.getTime(), Calendar.DAY_OF_MONTH));
        if (lists.size() > 0) {
            HnInspectionTaskGenService.log.info("{},今天是节假日不巡检", HnInspectionTaskGenService.LOG_PREFIX);
            return;
        }
        //规则Id
        // final Long inspecitonRuleId = context.getJobDetail().getJobDataMap().getLong("hnInspectionRuleId");
        //规则
        try {
            final HnInspectionPlan rule = this.planRepository.findById(inspecitonRuleId).get();
            final Date startDateTime = rule.getStartDateTime();
            // 格式化计划开始时间到开始时间的凌晨0点
            final Date startDateTime0 = DateUtils.truncate(startDateTime, Calendar.DAY_OF_MONTH);

            final Date endDateTime = rule.getEndDateTime();
            // 格式化计划结束时间到结束时间的半夜0点
            final Date endDateTime0 = DateUtils.round(endDateTime, Calendar.DAY_OF_MONTH);

            // 只有当前时间在计划开始和结束范围内的，才生成任务
            if ((now.getTime() >= startDateTime0.getTime())
                    && (now.getTime() <= endDateTime0.getTime())) {
                // final LocalDateTime endTaskTime = startTaskTime.plusHours(rule.getDuration());
                HnInspectionTaskGenService.log.info("{},当前时间在计划开始和结束范围内，准备生成任务, {}:{}:{}",
                        HnInspectionTaskGenService.LOG_PREFIX, nowStr, startDateTime0,
                        endDateTime0);
                final Date endTaskTime = DateUtils.addHours(now, rule.getDuration());
                HnInspectionTaskGenService.log.info("{},任务结束时间: {}", HnInspectionTaskGenService.LOG_PREFIX,
                        endTaskTime);
                final HnInspectionTask task = new HnInspectionTask();
                //调用接口取资产
                final Map<String, Object> queryMap = new HashMap<>();
                queryMap.put("s_submitTo", rule.getInstitutionName());
                // 2021/2/16 日巡检，过滤资产使用状态为在用的
                queryMap.put("s_statusCode", "using");
                final ResultListDTO<Map<String, Object>> resultDTO = this.dcamMicroService.searchAssets(queryMap);
                if (resultDTO.isSuccess() && !resultDTO.getData().isEmpty()) {
                    final List<HnInspectionTaskAsset> assets = new ArrayList<>();
                    resultDTO.getData().forEach(t -> {
                        final HnInspectionTaskAsset asset = this.hnInspectionTaskAssetConverter.toModel(t);
                        asset.setTask(task);
                        assets.add(asset);
                    });
                    task.setAssets(assets);
                }
                task.setCode(this.hnInspectionTaskCodeGenerator.generateCode());
                task.setHnInspectionPlan(rule);
                task.setStartDateTime(now);
                task.setEndDateTime(endTaskTime);
                task.setInstitutionCode(rule.getInstitutionCode());
                task.setInstitutionName(rule.getInstitutionName());
                task.setStatus(HnInspectionTaskStatus.notStarted);
                final List<HnInspectionItem> items = this.hnInspectionItemRepository.findByPlansId(inspecitonRuleId);
                final List<HnInspectionTaskItemValue> itemValues = new ArrayList<>();
                items.stream().map(t -> {
                    final HnInspectionTaskItemValue value = new HnInspectionTaskItemValue();
                    value.setItem(t);
                    value.setTask(task);
                    value.setStatus(HnInspectionTaskItemStatus.uninspected);
                    return value;
                }).forEach(itemValues::add);
                task.setItemValues(itemValues);

                this.taskRepository.save(task);

                //查询当前厅局的一线运维人员
                final Institutions institution = this.institutionsRepository.findByCode(rule.getInstitutionCode());
                final List<String> users =
                        institution.getResidents().stream().map(ResidentUser::getUsername).collect(Collectors.toList());
                //一线运维组长
                // users.add(rule.getUserCode());

                if (!users.isEmpty()) {
                    final NoticeRecordDTO notice = new NoticeRecordDTO();
                    notice.setTitle("日巡检任务");
                    notice.setType(
                            Lists.newArrayList(DCOMConstants.INFORM_TYPE_NOTICE, NoticeConsts.INFORM_TYPE_DINGDING));
                    notice.setAppCode("dcom");
                    final NoticeRecordSystemDTO sys = new NoticeRecordSystemDTO();
                    sys.setContent("您有开始于 " + nowStr + "的日巡检任务");
                    sys.setNoticeType("日巡检任务");
                    sys.setNoticeRoute("hn_hnInspectionTask");
                    final JSONObject info = new JSONObject();
                    info.put("s_id", task.getId());
                    sys.setBusinessInfo(info.toString());
                    sys.setUsers(users);
                    notice.setSystem(sys);

                    // 添加钉钉通知
                    final NoticeDingDTO toDing = new NoticeDingDTO();
                    toDing.setMsgtype("link");
                    toDing.setUsers(users);
                    final Map<String, String> linkParams = Maps.newHashMap();
                    linkParams.put("messageUrl", "eapp://pages/inspection/table/table?type=day");
                    linkParams.put("picUrl", "@lALPDeRETJL6S3XMtMy0");
                    linkParams.put("title", "日巡检任务");
                    linkParams.put("text", "您有开始于 " + nowStr + "的日巡检任务");
                    toDing.setJsonBody(JsonUtils.pojoToJson(linkParams));
                    notice.setDing(toDing);

                    this.noticeMicroService.createNotification(JsonUtils.pojoToJson(notice));
                    HnInspectionTaskGenService.log.info("{}, 给一线运维人员发送通知：{}", HnInspectionTaskGenService.LOG_PREFIX,
                            users.toString());
                }
            }
            // 如果当前时间小于计划开始时间，说明是用户提前设置，不做禁用操作
            else if (now.getTime() < startDateTime0.getTime()) {
                HnInspectionTaskGenService.log.info("{}, 计划的开始时间是未来时间，不生成任务, {}:{}",
                        HnInspectionTaskGenService.LOG_PREFIX, nowStr, startDateTime0);
            }
            // 当前时间大于计划结束时间，停止任务
            else {
                HnInspectionTaskGenService.log.info("{}, 现在的时间已经是计划的结束时间之后，禁用计划, {}:{}",
                        HnInspectionTaskGenService.LOG_PREFIX, nowStr, endDateTime0);
                this.jobMgrService.pauseJob(rule.getCode());
                this.jobMgrService.deleteJob(rule.getCode());
                rule.setDisabled(true);
                this.planRepository.save(rule);
            }
        } catch (final Exception e) {
            HnInspectionTaskGenService.log.error(e.getMessage(), e);
        }

    }

    //    private Date localDateTime2Date(final LocalDateTime localDateTime) {
    //        final ZoneId zoneId = ZoneId.systemDefault();
    //        final ZonedDateTime zdt = localDateTime.atZone(zoneId);
    //        return Date.from(zdt.toInstant());
    //    }

}
